﻿using AppWebApi.Authorization;
using AppWebApi.Models;
using AppWebApi.Models.Dtos;
using AppWebApi.Models.Dtos.PersonDtos;
using AppWebApi.Models.Form;
using AppWebApi.Services;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Modules;
using Modules.Base;
using Modules.CheckIn;
using Modules.CheckIn.Entitys;
using Modules.FaceScan;
using Modules.FaceScan.Entitys;
using Modules.Manager;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.System.Security;
using Org.BouncyCastle.Utilities.Encoders;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching.Redis;
using PmSoft.Entity;
using PmSoft.Exceptions;
using PmSoft.FileStorage;
using PmSoft.Utilities;
using static Modules.CheckIn.CheckInDetailConstants;

namespace AppWebApi.Controllers
{
    /// <summary>
    /// App业务相关接口
    /// </summary>
    [ApiController]
    [Route("/api/v1/app")]
    [AppAuthorization(UserType.Worker, UserType.Manager)]
    public class HomeController : ControllerBase
    {
        private readonly PersonService personService;
        private readonly FacePhotoService personFaceService;
        private readonly IFileStorage fileStorage;
        private readonly AppService appService;
        private readonly IPSearcher iPSearcher;
        private readonly IApplicationContext applicationContext;
        private readonly IMapper mapper;
        private readonly ILogger logger;
        private readonly ProjectPositionService projectPositionService;
        private readonly ManagerService managerService;
        private readonly ProjectGroupMemberService projectGroupMemberService;
        private readonly SecurityService securityService;
        private readonly PmSoftRedisCache redisCache;
        private readonly FaceScanService faceScanService;
        private readonly IConfiguration configuration;

        #region 当前请求的用户

        private AppUserInfo _currentUser;

        /// <summary>
        /// 当前请求的用户
        /// </summary>
        private AppUserInfo currentUser
        {
            get
            {
                if (_currentUser != null)
                    return _currentUser;
                if (applicationContext.CurrentUser == null || applicationContext.CurrentUser is not AppUserInfo user)
                    throw new BusinessException("未授权访问");
                _currentUser = user;
                return _currentUser;
            }
        }

        #endregion 当前请求的用户

        public HomeController(PersonService personService, FacePhotoService personFaceService, IFileStorage fileStorage, IPSearcher iPSearcher, IApplicationContext applicationContext, IMapper mapper, AppService appService, ILogger<HomeController> logger, ProjectPositionService projectPositionService, ManagerService managerService, ProjectGroupMemberService projectGroupMemberService, SecurityService securityService, PmSoftRedisCache redisCache, FaceScanService faceScanService, IConfiguration configuration)
        {
            this.personService = personService;
            this.personFaceService = personFaceService;
            this.fileStorage = fileStorage;
            this.iPSearcher = iPSearcher;
            this.applicationContext = applicationContext;
            this.mapper = mapper;
            this.appService = appService;
            this.logger = logger;
            this.projectPositionService = projectPositionService;
            this.managerService = managerService;
            this.projectGroupMemberService = projectGroupMemberService;
            this.securityService = securityService;
            this.redisCache = redisCache;
            this.faceScanService = faceScanService;
            this.configuration = configuration;
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetUserInfo")]
        [AppAuthorization]
        public object GetUserInfo()
        {
            PersonInfo? personInfo = personService.GetPersonByCardNo(currentUser.IdCard);
            if (personInfo == null)
                return ApiResult.Failure("没查询到人员信息").Encrypt();
            PersonInfoDto personDto = personInfo.AsDto();

            #region 获取流

            byte[] objectData = personFaceService.GetCardPhotoData(personInfo.CardNumber);
            if (objectData.Length > 0)
                personDto.Base64PhotoStr = Base64.ToBase64String(objectData);

            #endregion 获取流

            return ApiResult.Success("成功", personDto).Encrypt();
        }

        /// <summary>
        /// 获取人脸对比动作（劳资专管员和工人都可以用）
        /// </summary>
        /// <returns></returns>
        [HttpGet("create_unbind_scan")]
        public ApiResult CreateUnbindScan()
        {
            var scanRecord = faceScanService.CreateFaceScan(currentUser.IdCard, FaceScanReferType.CheckIn, 数据来源.APP);
            return ApiResult.Success("成功", new
            {
                ScanCode = scanRecord.ScanCode,
                CardNumber = currentUser.IdCard,
                Actions = scanRecord.Actions,
                TimeSpan = DateTime.Now.ToTimeStamp()
            }).Encrypt();
        }

        /// <summary>
        /// 创建解绑人类识别
        /// </summary>
        /// <returns></returns>
        [HttpGet("create_checkin_scan")]
        public ApiResult CreateCheckinScan()
        {
            var scanRecord = faceScanService.CreateFaceScan(currentUser.IdCard, FaceScanReferType.CheckIn, 数据来源.APP);
            return ApiResult.Success("成功", new
            {
                ScanCode = scanRecord.ScanCode,
                CardNumber = currentUser.IdCard,
                Actions = scanRecord.Actions,
                TimeSpan = DateTime.Now.ToTimeStamp()
            }).Encrypt();
        }

        #region 项目

        /// <summary>
        /// 查询我的项目信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetProjects")]
        [AppAuthorization(UserType.Worker, UserType.Manager)]
        public object GetProjects()
        {
            if (currentUser.Type != UserType.Manager)
            {
                var data = appService.GetProjects(currentUser.ObjectId);
                return ApiResult.Success("成功", data).Encrypt();
            }
            else
            {
                var data = appService.GetManagerProjects(currentUser.ObjectId);
                return ApiResult.Success("成功", data).Encrypt();
            }
        }

        /// <summary>
        /// 新增项目位置信息
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("AddProjectPosition")]
        [AppAuthorization(UserType.Manager)]
        public object AddProjectPosition([FromBody] EncryptMess<ProjectPositionEditForm> req)
        {
            ProjectPositionEditForm? form = req.GetParame();

            #region 字段非空验证

            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.ProjectId.HasValue)
                return ApiResult.Failure("项目id不能为空").Encrypt();
            if (!form.Lat.HasValue)
                return ApiResult.Failure("纬度不能为空").Encrypt();
            if (!form.Lng.HasValue)
                return ApiResult.Failure("经度不能为空").Encrypt();
            if (!form.AttendanceScope.HasValue)
                return ApiResult.Failure("考勤范围不能为空").Encrypt();
            if (string.IsNullOrEmpty(form.Address))
                return ApiResult.Failure("位置信息不能为空").Encrypt();

            #endregion 字段非空验证

            ProjectPosition entity = mapper.Map<ProjectPosition>(form);
            projectPositionService.Create(entity);
            return ApiResult.Success("新增成功").Encrypt();
        }

        /// <summary>
        /// 删除项目坐标
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("DeleteProjectPosition")]
        [AppAuthorization(UserType.Manager)]
        public object DeleteProjectPosition([FromBody] EncryptMess<ProjectPositionEditForm> req)
        {
            ProjectPositionEditForm? form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.Id.HasValue)
                return ApiResult.Failure("id不能为空").Encrypt();
            projectPositionService.Delete(form.Id.Value);
            return ApiResult.Success("删除成功").Encrypt();
        }

        /// <summary>
        /// 切换项目
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("UpdateDefaultProject")]
        [AppAuthorization(UserType.Manager)]
        public object UpdateDefaultProject([FromBody] EncryptMess<UpdateDefaultProjectQuery> req)
        {
            UpdateDefaultProjectQuery? form = req.GetParame();
            if (form == null) return ApiResult.Failure("参数无法解析").Encrypt();
            ManagerInfo? managerInfo = managerService.GetManagerInfo(currentUser.ObjectId);
            if (managerInfo == null)
                return ApiResult.Failure("当前人员信息不存在").Encrypt();
            managerInfo.ProjectId = form.ProjectId;
            managerService.Update(managerInfo);
            return ApiResult.Success("项目切换成功").Encrypt();
        }

        #endregion 项目

        #region 实名采集

        /// <summary>
        /// 根据身份证查询人员信息
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("GetPersonByCardNumber")]
        [AppAuthorization(UserType.Manager)]
        public object GetPersonByCardNumber([FromBody] EncryptMess<PersonByCardNumberQuery> req)
        {
            PersonByCardNumberQuery? form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            PersonInfo? personInfo = personService.GetPersonByCardNo(form.CardNumber);
            if (personInfo == null)
                return ApiResult.Failure("没查询到人员信息").Encrypt();

            PersonInfoDto dto = personInfo.AsDto();

            #region 获取流

            byte[] objectData = personFaceService.GetCardPhotoData(personInfo.CardNumber);
            if (objectData.Length > 0)
                dto.Base64PhotoStr = Base64.ToBase64String(objectData);

            #endregion 获取流

            return ApiResult.Success("成功", dto).Encrypt();
        }

        /// <summary>
        /// 根据身份证查询人员信息(模糊查询)
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("SearchPersonByCardNumber")]
        [AppAuthorization(UserType.Manager)]
        public ApiResult SearchPersonByCardNumber([FromBody] EncryptMess<PersonByCardNumberQuery> req)
        {
            PersonByCardNumberQuery? form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            IEnumerable<PersonInfo> personInfos = personService.SearchPersonByCardNumber(form.CardNumber, currentUser.ObjectId);

            List<PersonInfoDto> dtos = new();
            foreach (var item in personInfos)
            {
                PersonInfoDto dto = item.AsDto();
                dtos.Add(dto);
            }
            return ApiResult.Success("成功", dtos).Encrypt();
        }

        /// <summary>
        /// 替换核验照片（工人考勤后手动替换）
        /// </summary>
        /// <returns></returns>
        [HttpPost("UpdatePersonFaceByPerson")]
        [AppAuthorization(UserType.Worker)]
        public async Task<ApiResult> UpdatePersonFaceByPersonAsync()
        {
            IEnumerable<CheckInDetail> checkInDetails = await appService.GetRedisCheckinDetails(currentUser.IdCard);
            if (checkInDetails.Any())
            {
                string filePath = $"{currentUser.IdCard}/Appauth_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}";

                #region 获取流

                byte[] objectData = appService.GetCheckinPhoto(checkInDetails.OrderByDescending(a => a.CreateTime).FirstOrDefault()?.FacePath ?? "");
                if (objectData.Length > 0)
                {
                    #region 上传到minio

                    await fileStorage.PutFileAsync(FileBuckets.Person, filePath, objectData);

                    #endregion 上传到minio
                }

                #endregion 获取流

                FacePhoto? personFace = personFaceService.GetPersonFaceByIdCard(currentUser.IdCard);
                if (personFace == null)
                    return ApiResult.Failure("人员信息不存在").Encrypt();
                personFace.VerifyPhoto = filePath;
                personFace.VerifyPhotover = personFace.VerifyPhotover == null ? 1 : personFace.VerifyPhotover + 1;
                personFace.VerifyPhotoTime = DateTime.Now;
                personFaceService.Update(personFace);
            }
            return ApiResult.Success($"人员{currentUser.IdCard}核验照片替换成功").Encrypt();
        }

        /// <summary>
        /// 替换核验照片（实名采集提交）
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("UpdatePersonFace")]
        [AppAuthorization(UserType.Manager)]
        public async Task<ApiResult> UpdatePersonFaceAsync([FromBody] EncryptMess<PersonFaceEditForm> req)
        {
            PersonFaceEditForm? form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            await appService.UpdatePersonFacePhotoAsync(form);
            return ApiResult.Success($"人员{form.IdCard}实名采集成功").Encrypt();
        }

        #endregion 实名采集

        #region 工人花名册

        /// <summary>
        /// 查询花名册信息
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("GetPersons")]
        [AppAuthorization(UserType.Worker, UserType.Manager)]
        public object GetPersons([FromBody] EncryptMess<UserEmployeeQuery> req)
        {
            UserEmployeeQuery query = req.GetParame();
            if (query == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            List<UserEmployeeDto> dtos = new();
            if (currentUser.Type == UserType.Manager)
                return ApiResult.Success("成功", appService.GetManagerMembers(currentUser.ObjectId, query)).Encrypt();
            else
                return ApiResult.Success("成功", appService.GetWorkerMembers(currentUser.ObjectId, query)).Encrypt();
        }

        #endregion 工人花名册

        #region 我的班组

        /// <summary>
        /// 查询我的班组列表
        /// </summary>
        /// <returns></returns>
        [HttpPost("GetGroups")]
        [AppAuthorization(UserType.Worker)]
        public object GetGroups()
        {
            IEnumerable<ProjectGroupMember> members = projectGroupMemberService.GetProjectGroupMembersByPersonId(currentUser.ObjectId);
            return ApiResult.Success("成功", members.AsMyGroups()).Encrypt();
        }

        #endregion 我的班组

        #region 考勤统计 工人

        /// <summary>
        /// 查看考勤-统计
        /// </summary>
        /// <returns></returns>
        [HttpPost("GetCheckinReport")]
        [AppAuthorization(UserType.Worker)]
        public object GetCheckinReport([FromBody] EncryptMess<CheckinReportQuery> req)
        {
            CheckinReportQuery form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.ProjectGroupMemberId.HasValue)
                return ApiResult.Failure("请选择班组").Encrypt();
            var data = appService.GetCheckinReport(form.ProjectGroupMemberId.Value);
            return ApiResult.Success($"成功", data).Encrypt();
        }

        /// <summary>
        /// 查看考勤-明细按月份赛选
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("GetCheckInDetails")]
        [AppAuthorization(UserType.Worker)]
        public object GetCheckInDetails([FromBody] EncryptMess<CheckInDetailsQuery> req)
        {
            CheckInDetailsQuery? form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.CheckDate.HasValue)
                return ApiResult.Failure("考勤月份不能为空").Encrypt();
            if (!form.ProjectGroupMemberId.HasValue)
                return ApiResult.Failure("请选择班组").Encrypt();
            PersonInfo? personInfo = personService.GetPersonByCardNo(currentUser.IdCard);
            if (personInfo == null)
                return ApiResult.Failure("没查询到人员信息").Encrypt();

            if (currentUser.Type != UserType.Worker)
                return ApiResult.Failure("当前").Encrypt();

            var projectGroupMembers = projectGroupMemberService.GetProjectGroupMembersByPersonId(personInfo.PersonId);
            if (!projectGroupMembers.Any(i => i.Id == form.ProjectGroupMemberId))
                return ApiResult.Failure("当前人员没有在任何班组进场").Encrypt();

            logger.LogInformation($"ProjectGroupMemberId:{form.ProjectGroupMemberId.Value} personInfo:{personInfo.PersonId} memberids:{string.Join(',', projectGroupMembers.Select(i => i.Id))}");
            var checkInDetailService = applicationContext.GetService<CheckInDetailService>();
            IEnumerable<CheckInDetailDto> checkInDetailDtos = checkInDetailService.GetCheckinDetailsByMonthAndMemberId(form.CheckDate.Value, form.ProjectGroupMemberId.Value).AsAppDtos();
            return ApiResult.Success($"成功", checkInDetailDtos).Encrypt();
        }

        #endregion 考勤统计 工人

        #region 工人考勤查询 劳资专管员

        /// <summary>
        /// 工人考勤统计
        /// </summary>
        /// <returns></returns>
        [HttpPost("GetWorkerCheckinReport")]
        [AppAuthorization(UserType.Manager)]
        public object GetWorkerCheckinReport()
        {
            ManagerInfo? managerInfo = managerService.GetManagerInfo(currentUser.ObjectId);
            if (managerInfo == null)
                return ApiResult.Failure("没查询到人员信息").Encrypt();
            var data = appService.GetWorkerCheckinReport(managerInfo.ProjectId);
            return ApiResult.Success("成功", data).Encrypt();
        }

        /// <summary>
        /// 获取工人考勤明细
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost("GetWorkerCkeckinDetails")]
        [AppAuthorization(UserType.Manager)]
        public object GetWorkerCkeckinDetails([FromBody] EncryptMess<WorkerCkeckinDetailsQuery> req)
        {
            WorkerCkeckinDetailsQuery form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.Month.HasValue)
                return ApiResult.Failure("考勤月份不能为空").Encrypt();
            ManagerInfo? managerInfo = managerService.GetManagerInfo(currentUser.ObjectId);
            if (managerInfo == null)
                return ApiResult.Failure("没查询到人员信息").Encrypt();
            var data = appService.GetWorkerCkeckinDetails(form, managerInfo.ProjectId);
            return ApiResult.Success("成功", data.AsAppDtos()).Encrypt();
        }

        /// <summary>
        /// 查询考情详情
        /// </summary>
        /// <returns></returns>
        [HttpPost("GetCheckinDetail")]
        [AppAuthorization]
        public object GetCheckinDetail([FromBody] EncryptMess<GetCheckinDetailQuery> req)
        {
            GetCheckinDetailQuery form = req.GetParame();
            if (form == null)
                return ApiResult.Failure("参数无法解析").Encrypt();
            if (!form.Month.HasValue)
                return ApiResult.Failure("考勤月份不能为空").Encrypt();
            if (string.IsNullOrEmpty(form.CheckinDetailId))
                return ApiResult.Failure("明细id不能为空").Encrypt();
            CheckInDetail? checkInDetail = appService.GetCheckinDetail(form.Month.Value, form.CheckinDetailId);
            if (checkInDetail == null)
                return ApiResult.Failure("没有查询到考勤明细数据").Encrypt();
            return ApiResult.Success("成功", checkInDetail.AsAppDetailDto()).Encrypt();
        }

        #endregion 工人考勤查询 劳资专管员

        #region 身份切换

        /// <summary>
        /// 登录身份切换
        /// </summary>
        /// <returns></returns>
        //[HttpPost("IdentitySwitching")]
        //[AppAuthorization]
        //public object IdentitySwitching()
        //{
        //    if (currentUser.Type == UserType.Worker)
        //    {
        //        //当前登录人是工人，需要切换到劳资专管员
        //        ManagerInfo? managerInfo = managerService.GetManagerInfo(currentUser.IdCard);
        //        if (managerInfo == null)
        //            return ApiResult.Failure($"没有查询到{currentUser.IdCard}的劳资专管员权限").Encrypt();
        //        var managerInfoDto = managerInfo.AsDto();
        //        var security = securityService.GetSysSecurity(managerInfo.SecurityId);
        //        managerInfoDto.IsAuth = security?.IsAuth ?? false;
        //        if (managerInfoDto.IsAuth)
        //            managerInfoDto.Token = appService.GetManagerToken(security.SecurityId, security.UserType, managerInfo.Cardno);
        //        #region 获取流
        //        byte[] objectData = personFaceService.GetCardPhotoData(managerInfo.Cardno);
        //        if (objectData.Length > 0)
        //            managerInfoDto.Base64PhotoStr = Base64.ToBase64String(objectData);
        //        #endregion
        //        return ApiResult.Success("成功",managerInfoDto).Encrypt();
        //    }
        //    else if (currentUser.Type == UserType.Manager)
        //    {
        //        //劳资专管员
        //    }
        //}

        #endregion 身份切换

        #region 查询当前登录人员在场的班组

        /// <summary>
        /// 查询当前登录人员在场的班组
        /// </summary>
        /// <returns></returns>
        [HttpGet("myOnlineGroup")]
        [AppAuthorization(UserType.Worker)]
        public ApiResult GetOnlineGroup()
        {
            ProjectAppDto? dto = appService.GetProjects(currentUser.ObjectId, true).FirstOrDefault();
            if (dto == null)
                return ApiResult.Failure("对不起，您当前没在任何班组进场，不能考勤").Encrypt();
            return ApiResult.Success("成功", dto).Encrypt();
        }

        #endregion 查询当前登录人员在场的班组
    }
}